/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package edu.isi.pegasus.planner.subworkflow.estimator.implementation;

import edu.isi.pegasus.planner.classes.ADag;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.Random;

/**
 *
 * @author wchen
 *
 **/

  class addFakeNode implements Runnable
{
     private ADag subDag;
     Thread runner;
     private boolean done;
     private edu.isi.pegasus.planner.classes.Job headNode;
     private edu.isi.pegasus.planner.classes.Job rearNode;
     private int start;
     private int end;
    @SuppressWarnings("static-access")
     public void getDone()
     {
         while(!done){
             try
             {
                Thread.currentThread().sleep(1000);
             }
             catch (Exception e)
             {
                 e.printStackTrace();
             }

         }
     }
     public addFakeNode(ADag subDag, int start, int end,edu.isi.pegasus.planner.classes.Job headNode,edu.isi.pegasus.planner.classes.Job rearNode)
     {
            this.headNode = headNode;
            this.rearNode = rearNode;
            this.start    = start;
            this.end      = end;
            runner        = new  Thread(this, "");
            this.subDag   = subDag;
            this.done     = false;
            runner.start();
     }
    public void run()
    {
        for(int i = start ; i< end; i++ )
        {
            edu.isi.pegasus.planner.classes.Job job =
                    (edu.isi.pegasus.planner.classes.Job)subDag.vJobSubInfos.get(i);

            if(job.jobID.equals(headNode.jobID) || job.jobID.equals(rearNode.jobID))
                continue;
            if(subDag.getChildren(job.jobID).size() == 0)
            {
                subDag.addNewRelation(job.jobID, rearNode.jobID);
                //subDag.addNewRelation(null, null);
            }
            if(subDag.getParents(job.jobID).size() == 0 )
                subDag.addNewRelation(headNode.jobID, job.jobID);
        }
        this.done = true;
    }
}

 

public class ParallelThread{
    public static void main(String[] args)
    {
        Map map = new HashMap<String, Double>();
        map.put("A", 1.1);
        map.put("B", 2.2);
        //getSizeMapThread thread1 = new getSizeMapThread(0,2,map,"");
        //thread1.runner.start();
        //double sum  = thread1.getSum();
        try{
            Thread.currentThread().sleep(1000);
        }catch (Exception e)
        {

        }
        //System.out.println(sum);
    }

}


class getCPUTime implements Runnable
{
     private ADag subDag;
     Thread runner;
     private boolean done;
     private int index;
     private int size;
     private Map mJob2Time;
     private double runtime;
     public double getRuntime()
     {
         return runtime;
     }
    @SuppressWarnings("static-access")
     public void getDone()
     {
         while(!done){
             try
             {
                Thread.currentThread().sleep(1000);
             }
             catch (Exception e)
             {
                 e.printStackTrace();
             }

         }
     }
     public getCPUTime(ADag subDag, int index,
             Map mJob2Time)
     {
            this.index    = index;
            this.size     = subDag.getNoOfJobs();
            runner        = new  Thread(this, "");
            this.subDag   = subDag;
            this.done     = false;
            this.runtime  = 0.0;
            this.mJob2Time= Collections.synchronizedMap(mJob2Time);
            runner.start();
     }
    public void run()
    {
        
        for(int i = 0 ; i%size == index && i < size; i++ )
        {
          edu.isi.pegasus.planner.classes.Job job =
                 (edu.isi.pegasus.planner.classes.Job)subDag.vJobSubInfos.get(i);
            runtime += (Double)mJob2Time.get(job.jobID);
        }
        this.done = true;
    }
}
 class getCriticalPath implements Runnable
{
     private ADag subDag;
     Thread runner;
     private boolean done;
     private Map pathMap;
     private int index;
     private int size;
     private Map mJob2Time;
     private int slot;
     private LinkedList mQueue;
    @SuppressWarnings("static-access")
     public void getDone()
     {
         while(!done){
             try
             {
                Thread.currentThread().sleep(1000);
             }
             catch (Exception e)
             {
                 e.printStackTrace();
             }

         }
     }
     public getCriticalPath(ADag subDag, Map pathMap, int index, int slot,
             Map mJob2Time, LinkedList mQueue)
     {
            this.mQueue  = mQueue;
            this.pathMap = pathMap;
            this.index    = index;
            this.size     = subDag.getNoOfJobs();
            this.slot     = slot;
            runner        = new  Thread(this, "");
            this.subDag   = subDag;
            this.done     = false;
            this.mJob2Time= Collections.synchronizedMap(mJob2Time);
            runner.start();
     }
     
     public void run(){
         boolean hasdone = true;

         //picks up one
         while(true)
         {
            synchronized(pathMap)
             {
                 int mapsize = pathMap.size();
//                 System.out.println("size: " + mapsize);
//                 if(mapsize==8046)
//                     System.out.println("I dont know");
                 if(mapsize==size)
                     break;

             }
             String jobID = "";
             synchronized (mQueue)
             {
                if(mQueue.isEmpty())continue;
                jobID = (String)mQueue.getFirst();
                try{
                    mQueue.remove(jobID);
                }catch (Exception e)
                {
                    e.printStackTrace();
                }

             }
             synchronized(pathMap)
             {
                 if(pathMap.containsKey(jobID))
                    continue;
             }

                 if(!mJob2Time.containsKey(jobID))
                    mJob2Time.put(jobID, 0.0);
                 double runtime = (Double)mJob2Time.get(jobID);
                 boolean hasall = true;
                 double runtime3 = 0.0;
                 double runtime2 = 0.0;
               for(Iterator it = subDag.getChildren(jobID).iterator();it.hasNext();)
               {

                   String child = (String)it.next();
                   synchronized(pathMap){
                       if(!pathMap.containsKey(child))
                       {
                           hasall = false;
                           hasdone = false;
                           synchronized(mQueue){
                               if(!mQueue.contains(child))
                                  mQueue.addFirst(child);
                           }
                       }
                       else
                       {
                       //stupi
                       if(!mJob2Time.containsKey(child))
                            mJob2Time.put(child, 0.0);
                           runtime3 = (Double)mJob2Time.get(child);
                           if(runtime3 > runtime2)runtime2 = runtime3;
                       }
                   }

               }
                 if(hasall)
                 {
                     runtime += runtime2;
                     synchronized(pathMap){
                        pathMap.put(jobID, runtime);
                     }
                     for(Iterator it = subDag.getParents(jobID).iterator(); it.hasNext();)
                     {
                         String parent = (String)it.next();
                         synchronized(pathMap){
                            synchronized(mQueue){
                             if(!pathMap.containsKey(parent) && !mQueue.contains(parent))
                             {
                                 mQueue.addFirst(parent);
                             }
                            }
                         }

                     }

                 }
                 else
                 {
                     synchronized(mQueue){
                        mQueue.addLast(jobID);
                     }
                 }
         }
         this.done = true;

         
     }
     
}

 class getRankParallel implements Runnable
{
     private ADag subDag;
     Thread runner;
     private boolean done;
     private Map job2rank;
     private int index;
     private int size;
     private Map mJob2Time;
     private int slot;
     private LinkedList mQueue;
     private Map rank2job;
     private Map weight;
    @SuppressWarnings("static-access")
     public void getDone()
     {
         while(!done){
             try
             {
                Thread.currentThread().sleep(1000);
             }
             catch (Exception e)
             {
                 e.printStackTrace();
             }

         }
     }
     public getRankParallel(ADag subDag, Map job2rank, int index, int slot,
             Map mJob2Time, LinkedList mQueue, Map rank2job, Map weight)
     {
            this.mQueue  = mQueue;
            this.job2rank = job2rank;
            this.index    = index;
            this.size     = subDag.getNoOfJobs();
            this.slot     = slot;
            runner        = new  Thread(this, "");
            this.subDag   = subDag;
            this.done     = false;
            this.mJob2Time= Collections.synchronizedMap(mJob2Time);
            this.rank2job  = rank2job;
            this.weight   = weight;
            runner.start();
     }

     public void run(){
         boolean hasdone = true;
         while(true)
         {
            synchronized(job2rank)
             {
                 int mapsize = job2rank.size();
//                 System.out.println("size: " + mapsize);
//                 if(mapsize==8046)
//                     System.out.println("I dont know");
                 if(mapsize==size)
                     break;

             }
             String jobID = "";
             synchronized (mQueue)
             {
                if(mQueue.isEmpty())continue;
                jobID = (String)mQueue.getFirst();
                try{
                    mQueue.remove(jobID);
                }catch (Exception e)
                {
                    e.printStackTrace();
                }

             }
//             synchronized
//                if(job2rank.containsKey(jobID))
//                {
//                    continue;
//                }
                           if(!mJob2Time.containsKey(jobID))
                    mJob2Time.put(jobID, 0.0);
                 double runtime = (Double)mJob2Time.get(jobID);
                 boolean hasall = true;
                 double runtime3 = 0.0;
                 double runtime2 = 0.0;
                 double rank = 0.0;
               for(Iterator it = subDag.getChildren(jobID).iterator();it.hasNext();)
               {

                   String child = (String)it.next();
                   synchronized(job2rank){
                       if(!job2rank.containsKey(child))
                       {
                           hasall = false;
                           hasdone = false;
                           synchronized(mQueue){
                               if(!mQueue.contains(child))
                                  mQueue.addFirst(child);
                           }
                       }
                       else
                       {
                       //stupi
                       if(!mJob2Time.containsKey(child))
                            mJob2Time.put(child, 0.0);
                           runtime3 = (Double)mJob2Time.get(child);
                           if(runtime3 > runtime2)runtime2 = runtime3;
                       }
                   }

               }
                 if(hasall)
                 {
                     rank = runtime + runtime2;
                     synchronized(job2rank){

                        Random generator = new Random();
                        while(rank2job.containsKey(rank))
                        {
                            double var = generator.nextDouble() / 100;
                            rank += var;
                            //System.out.println("Variation rank = " + rank + " var = " + var);
                        }
                        job2rank.put(jobID, rank);
                        rank2job.put(rank, jobID);
                        weight.put(rank, runtime);
                        job2rank.put(jobID, rank);
                     }
                     for(Iterator it = subDag.getParents(jobID).iterator(); it.hasNext();)
                     {
                         String parent = (String)it.next();
                         synchronized(job2rank){
                            synchronized(mQueue){
                             if(!job2rank.containsKey(parent) && !mQueue.contains(parent))
                             {
                                 mQueue.addFirst(parent);
                             }
                            }
                         }

                     }

                 }
                 else
                 {
                     synchronized(mQueue){
                        mQueue.addLast(jobID);
                     }
                 }
         }
         this.done = true;
     }


}